Implement Semantic Headings for Page Listing Detail
On this page
Now that we have an idea of the heading structure issues on the Listing Detail page, we can go about fixing them.
Heading Structure in a Component-Based Web Application
Because CampSpots is built in React, each page is a component that can either include all of its own markup or incorporate other components.
Looking at the source code for the Listing detail page template at components/page-listing-detail.js there is markup that will dynamically render the name and location of the site from JSON data, along with the description and amenities. The Date Picker component is brought in from another file.
Note that the MegaNav component is not included here. Inside of the entry point for our application, App.js includes a Header component that is rendered above the page component that matches the URL path thanks to some help from Reach Router.
The important thing to take away here is that different components can have their own heading levels that are independent from those in other components. When various components come together on a rendered page, we need to pay attention to the overall outline.
Remember, there should only be one H1 per page!
Recall the heading structure that the Web Developer Toolbar showed us:
All of the H2s are included in the MegaNav component, which is in turn brought into the page by the Header component in App.js.
The H4 (”August 2022”) is part of the date picker, which is brought in by the Listing Detail page template.
We need to update the Listing Detail to include additional heading levels to improve the semantic structure of the page.
🛠 Challenge: Add Heading Structure to Page Listing Detail
Your challenge is to build a heading structure for Listing Detail page template in page-listing-detail.js that represents the visual content hierarchy of the page.
Add headings to the page structure in such a way that Web Developer Toolbar’s document outline matches this content hierarchy:
- The MegaNav’s headings remain at the top
- The page’s location and content headings should all be nested below the CampSpot’s name.
- Each content section should follow a relevant heading.
A Note About the Missing H1
At the top of every page’s structure should be a single H1.
We’ve seen that our site is missing an H1, and we know that it needs to be above the H2s in the MegaNav.
This means that even though Cranberry Lake visually looks like a page title, it can’t be the page’s H1.
To get things started, we’ll update the listing’s name to be an h2 instead of a div:
<!-- page-listing-detail -->
<header
className="page-header"
style={{backgroundImage: `url(${headerImageUrl}`}}
>
<div className="page-header-content wide-layout">
<h2 className="listing-name">{data.listingName}</h2>
<p className="location">{data.location}</p>
</div>
</header>We will address the missing H1 later on.
Being constrained when fixing heading levels is a common scenario for teams. You can’t always create the perfect semantic structure you want, but getting the heading levels in order is a huge step in the right direction.
Video Transcript
We'll take a look at our page listing detail.
Okay. So within a listing, the page listing detail, we've got, we've got some headings in here, so I'm actually going to close the sidebar with command B. And I'm going to move our VScode over a little bit so that we can see a little bit of both. I'll kind of have a little, a little peek-a-boo of our browser here on the side.
So cranberry lake is so we've. I can kinda tell, you know, we've got location. Listing name is our dynamic heading here that says cranberry lake. So if we think about our overall page structure, cranberry lake should be. Probably the H1, maybe the h2, our challenge is that we already have h2s that have come before this heading.
And so to create the overall page structure, starting with h1 all the way at the top, we have a bit of a conundrum with our heading structure, and this comes up all the time. It's kind of irritating. You can't always create the exact structure you want because you have these constraints with the way the page is already set up.
Maybe you only have access to create headings within a part of the page. You know? So what I think we could do Right now for this purpose. I mean, we want an overall structure that makes sense. I think cranberry lake could become an h2 and we'll let an h1, for camp spots be the h1 up above the mega menu.
So let's start with our page content. We'll start off with h2 we'll structure, the content below that, and then we'll come back and revisit the So our listing name, I am going to. Select the opening and closing tags using command D on my Mac. So I can change both at once. I'm gonna change that from div to h2 following it is data location, and that's marked up as a paragraph.
I think that is probably sufficient. We have a little bit more semantic structure. We're going to wrap around this right after we finish headings. So I think for now leaving it as h2 with a paragraph following. Sets up a pretty nice structure for this kind of header area. At least as far as the text content is concerned
🛠 Solution: Adding Headings to Page Listing Detail
Adding Headings to Build a Page Structure
The camp site description is currently marked up as a div.
Since the description comes immediately after the h2 for the site title, we can mark it up as an h3.
The text “Amenities” introducing the section doesn’t currently have any tag surrounding it, even though visually it looks as important as the description. We can make it an h3 .
The “Calendar” heading also should be turned into an h3.
We can use the same classNames for each heading to apply styling. In our stylesheet, utility classes allow us to style a heading according to a design while choosing the correct heading level.
Here’s what the markup looks like now:
<!-- page-listing-detail -->
<div className="wide-layout two-parts-70-30">
<div>
<h3 className="h4-style">Description</h3>
<div className="description-text" dangerouslySetInnerHTML={{__html: sanitizeHtml(data.description)}} />
<h3 className="h4-style">Amenities</h3>
<ul className="amenity-icons grid">
{data.amenities.map((amenity, index) => {
return <li key={index}>
<Icon name={amenity} showText={true} />
</li>
})}
</ul>
</div>
<div>
<h3 className="h4-style">Calendar</h3>
<DatePicker />
</div>
</div>Don’t choose heading levels based on visual font size. That’s what CSS is for!
Checking our work in the browser, we can see that the headings have a bold style and a little margin under them. Making “Amenities” into a heading also improved the visual look of the page.
Video Transcript
Further down the page.
We also have description that's marked up as div. So since that's going to come after our h2 that we just marked up, I think that could be an h3. So I'll do command D select those, change it to an h3. Same with the amenities. It doesn't have any tag wrapping it. So I'm going to wrap it in an h3, because it really should be at the same level as description.
They're kind of, they have the same level of importance. They're kind of describing each section of this page. Same with calendar. That one could be an h3 as well. So now we have these signposts using our heading structure. So the last part of this, I'm going to hit command S to save, and that did give us a nice hot reload in our browser.
So now these headings have a bit more bolding amenities has a little bit of margin under it. So our style is improved calendar. Now it has a heading.
Analyze New Page Listing Detail Heading Structure
So now, if we run the Web Developer Toolbar extension again, we will see very different results.
So far we have Cranberry Lake as an h2with h3 headings for the other sections nested below it. The month and year for the date picker is also correctly nested below the Calendar heading.
Menu Structure is Subjective
The MegaNav takes up quite a bit of our page structure, which is a subjective choice.
I chose to mark up the top-level navigation menu items as headings because they contribute major areas to the page structure. These items have buttons nested inside for interactivity, contributing both semantic structure and keyboard/screen reader operability for the MegaNav.
No matter which approach you take in your own projects, make a healthy heading structure a priority for pages, and remember to test with a screen reader!
Video Transcript
So now if I run our web developer toolbar again. Cause I have to come back here to kind of regenerate the outline.
This looks much better. So we have cranberry lake. Now this whole page section kind of under our mega menu. It has the name of the listing, the description, the amenities, the calendar, July, 2022 is now nested, nicely under calendar. And we have image gallery. And so our mega menu does take up quite a bit of our page structure overall.
And so that's kind of a subjective choice to, to add that much heading structure to your mega menu. You, you might make a different choice and that's okay. But the, the utility that, that had was that up in our mega menu, there are heading like pieces of text. And so. It is nice to have, you know, content that's marked up with headings.
See, I think if you have any question about the utility of like how many headings are are, right. Kind of get that sweet spot. If you have questions about that, testing it with people who use screen readers all the time. Like that's your best bet. Because we don't always know what's best or what's most ergonomic.
I think having a healthy heading structure is the ideal. And kind of getting more nuanced within that. It helps to get user input. Sometimes so our heading structure for this page is way better than it was.
